//////////////////////////////////////////////////////////////////////////
//  This file contains routines to register / Unregister the 
//  Directshow filter 'Virtual Cam'
//  We do not use the inbuilt BaseClasses routines as we need to register as
//  a capture source
//////////////////////////////////////////////////////////////////////////
#pragma comment(lib, "kernel32")
#pragma comment(lib, "user32") 
#pragma comment(lib, "gdi32")
#pragma comment(lib, "advapi32")
#pragma comment(lib, "winmm")
#pragma comment(lib, "ole32")
#pragma comment(lib, "oleaut32")

//#ifdef _DEBUG
//    #pragma comment(lib, "strmbasd")
//#else
//    #pragma comment(lib, "strmbase")
//#endif


#include <streams.h>
#include <olectl.h>
#include <initguid.h>
#include <dllsetup.h>
#include "filters.h"
#include "INI.h"
#include <tchar.h>
#define CreateComObject(clsid, iid, var) CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, iid, (void **)&var);

STDAPI AMovieSetupRegisterServer( CLSID   clsServer, LPCWSTR szDescription, LPCWSTR szFileName, LPCWSTR szThreadingModel = L"Both", LPCWSTR szServerType     = L"InprocServer32" );
STDAPI AMovieSetupUnregisterServer( CLSID clsServer );




DEFINE_GUID(CLSID_VirtualFlashCam,
            0x1d6bbf77, 0xf379, 0x429c, 0x80,
			0x1a, 
			0xcd,
			0x07,
			0x2f,
			0x46,
			0xe9,
			0xa7);

DEFINE_GUID(CLSID_SetupCVCameraProp, 0x03025805, 0xa80b, 
0x46ff, 0x97, 0x7f, 0xda, 0xff, 0x11, 0x2e, 0xc6, 0xb7);


const AMOVIESETUP_MEDIATYPE AMSMediaTypesVCam = 
{ 
    &MEDIATYPE_Video, 
    &MEDIASUBTYPE_NULL 
};

const AMOVIESETUP_PIN AMSPinVCam=
{
    L"Output",             // Pin string name
    FALSE,                 // Is it rendered
    TRUE,                  // Is it an output
    FALSE,                 // Can we have none
    FALSE,                 // Can we have many
    &CLSID_NULL,           // Connects to filter
    NULL,                  // Connects to pin
    1,                     // Number of types
    &AMSMediaTypesVCam      // Pin Media types
};

const AMOVIESETUP_FILTER AMSFilterVCam =
{
    &CLSID_VirtualFlashCam,  // Filter CLSID
    L"Virtual Flash Cam",     // String name
    MERIT_DO_NOT_USE,      // Filter merit
    1,                     // Number pins
    &AMSPinVCam             // Pin details
};

CFactoryTemplate g_Templates[] = 
{
    {
        L"Virtual Flash Cam",
        &CLSID_VirtualFlashCam,
        CVCamera::CreateInstance,
        NULL,
        &AMSFilterVCam
    },

};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

STDAPI RegisterFilters( BOOL bRegister )
{
    HRESULT hr = NOERROR;
    WCHAR achFileName[MAX_PATH];
    char achTemp[MAX_PATH];
    ASSERT(g_hInst != 0);

    if( 0 == GetModuleFileNameA(g_hInst, achTemp, sizeof(achTemp))) 
        return AmHresultFromWin32(GetLastError());

    MultiByteToWideChar(CP_ACP, 0L, achTemp, lstrlenA(achTemp) + 1, 
                       achFileName, NUMELMS(achFileName));
  
    hr = CoInitialize(0);
	std::wstring m_strKeyValue =__W("");
	std::wstring m_strKeyName =__W("name");
    if(bRegister)
    {
		//TODO get info from ini file.
	 
	  std::wstring temp=achFileName;

	  int pos = temp.find_last_of(__W("\\"));
	  int length = temp.length();
	  length = length-( length - pos )+1;
	  temp = temp.substr(0,length);
	  CIniReader m_IniReader;
	  std::wstring m_strINIFile = temp;
	   m_strINIFile = m_strINIFile + __W("VirtCam.ini");
       m_IniReader.setINIFileName (m_strINIFile);
	   std::wstring m_strSectionName =__W("Virtual cam name");
	   

	   bool bExists = m_IniReader.sectionExists(m_strSectionName);
	   if(bExists)
	   {
		 m_strKeyValue = m_IniReader.getKeyValue(m_strKeyName,m_strSectionName);
	     if(m_strKeyValue != __W(""))
		 {
		 }
		 else
		 {
		  m_strKeyValue =  L"Virtual Flash Cam";
		 }
	   }
	   else
	   {
	      m_strKeyValue =  L"Virtual Flash Cam";
	   }
	

        hr = AMovieSetupRegisterServer(CLSID_VirtualFlashCam, m_strKeyValue.c_str(), achFileName, L"Both", L"InprocServer32");
    }

    if( SUCCEEDED(hr) )
    {
        IFilterMapper2 *fm = 0;
        hr = CreateComObject( CLSID_FilterMapper2, IID_IFilterMapper2, fm );
        if( SUCCEEDED(hr) )
        {
            if(bRegister)
            {
                IMoniker *pMoniker = 0;
                REGFILTER2 rf2;
                rf2.dwVersion = 1;
                rf2.dwMerit = MERIT_DO_NOT_USE;
                rf2.cPins = 1;
                rf2.rgPins = &AMSPinVCam;
                hr = fm->RegisterFilter(CLSID_VirtualFlashCam, m_strKeyValue.c_str(), &pMoniker, &CLSID_VideoInputDeviceCategory, NULL, &rf2);
            }
            else
            {
                hr = fm->UnregisterFilter(&CLSID_VideoInputDeviceCategory, 0, CLSID_VirtualFlashCam);
            }
        }

      // release interface
      //
      if(fm)
          fm->Release();
    }

    if( SUCCEEDED(hr) && !bRegister )
        hr = AMovieSetupUnregisterServer( CLSID_VirtualFlashCam );

    CoFreeUnusedLibraries();
    CoUninitialize();
    return hr;
}

STDAPI DllRegisterServer()
{
	
    return RegisterFilters(TRUE);
}

STDAPI DllUnregisterServer()
{
    return RegisterFilters(FALSE);
}

extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

HINSTANCE g_hInstance = NULL;

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{
	
	if(dwReason == DLL_PROCESS_ATTACH )
	{
	 g_hInstance = (HINSTANCE)hModule;
	}
	return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
